home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 24 / AACD 24.iso / AACD / Utilities / ttf2pt1PPC / src / ttf.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-05-24  |  37.2 KB  |  1,480 lines

  1. /*
  2.  * True Type Font to Adobe Type 1 font converter 
  3.  * By Mark Heath <mheath@netspace.net.au> 
  4.  * Based on ttf2pfa by Andrew Weeks <ccsaw@bath.ac.uk> 
  5.  * With help from Frank M. Siegert <fms@this.net> 
  6.  *
  7.  * see COPYRIGHT
  8.  *
  9.  */
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <string.h>
  13. #include <sys/types.h>
  14. #include <sys/stat.h>
  15. #include <fcntl.h>
  16. #include <time.h>
  17. #include <ctype.h>
  18. #include <math.h>
  19.  
  20. #ifndef WINDOWS
  21. #    include <unistd.h>
  22. #    include <netinet/in.h>
  23. #else
  24. #    include "windows.h"
  25. #endif
  26.  
  27. #include "ttf.h"
  28. #include "pt1.h"
  29. #include "global.h"
  30.  
  31. /* prototypes of call entries */
  32. static void openfont(char *fname, char *arg);
  33. static void closefont( void);
  34. static int getnglyphs ( void);
  35. static int glnames( GLYPH *glyph_list);
  36. static void glmetrics( GLYPH *glyph_list);
  37. static int glenc( GLYPH *glyph_list, int *encoding, int *unimap);
  38. static void fnmetrics( struct font_metrics *fm);
  39. static void glpath( int glyphno, GLYPH *glyph_list);
  40. static void kerning( GLYPH *glyph_list);
  41.  
  42. /* globals */
  43.  
  44. /* front-end descriptor */
  45. struct frontsw ttf_sw = {
  46.     /*name*/       "ttf",
  47.     /*descr*/      "built-in TTF support",
  48.     /*suffix*/     { "ttf" },
  49.     /*open*/       openfont,
  50.     /*close*/      closefont,
  51.     /*nglyphs*/    getnglyphs,
  52.     /*glnames*/    glnames,
  53.     /*glmetrics*/  glmetrics,
  54.     /*glenc*/      glenc,
  55.     /*fnmetrics*/  fnmetrics,
  56.     /*glpath*/     glpath,
  57.     /*kerning*/    kerning,
  58. };
  59.  
  60. /* statics */
  61.  
  62. static FILE    *ttf_file;
  63. static int      ttf_nglyphs, long_offsets;
  64.  
  65. static TTF_DIRECTORY *directory;
  66. static TTF_DIR_ENTRY *dir_entry;
  67. static char    *filebuffer;
  68. static char    *filebuffer_end;
  69. static TTF_NAME *name_table = NULL;
  70. static TTF_NAME_REC *name_record;
  71. static TTF_HEAD *head_table = NULL;
  72. static TTF_HHEA *hhea_table = NULL;
  73. static TTF_KERN *kern_table = NULL;
  74. static TTF_CMAP *cmap_table = NULL;
  75. static LONGHORMETRIC *hmtx_table = NULL;
  76. static TTF_GLYF *glyf_table;
  77. static BYTE    *glyf_start = NULL;
  78. static TTF_MAXP *maxp_table = NULL;
  79. static TTF_POST_HEAD *post_table = NULL;
  80. static union {
  81.     USHORT *sp;
  82.     ULONG  *lp;
  83. } loca_table;
  84. #define short_loca_table    loca_table.sp
  85. #define long_loca_table        loca_table.lp
  86.  
  87. static short    cmap_n_segs;
  88. static USHORT  *cmap_seg_start, *cmap_seg_end;
  89. static short   *cmap_idDelta, *cmap_idRangeOffset;
  90. static TTF_CMAP_FMT0  *encoding0;
  91. static int             enc_type;
  92.  
  93. static char     name_buffer[2000];
  94. static char    *name_fields[8];
  95.  
  96. static int enc_found_ms, enc_found_mac;
  97.  
  98. static char    *mac_glyph_names[258] = {
  99.     ".notdef", ".null", "CR",
  100.     "space", "exclam", "quotedbl", "numbersign",
  101.     "dollar", "percent", "ampersand", "quotesingle",
  102.     "parenleft", "parenright", "asterisk", "plus",
  103.     "comma", "hyphen", "period", "slash",
  104.     "zero", "one", "two", "three",
  105.     "four", "five", "six", "seven",
  106.     "eight", "nine", "colon", "semicolon",
  107.     "less", "equal", "greater", "question",
  108.     "at", "A", "B", "C",
  109.     "D", "E", "F", "G",
  110.     "H", "I", "J", "K",
  111.     "L", "M", "N", "O",
  112.     "P", "Q", "R", "S",
  113.     "T", "U", "V", "W",
  114.     "X", "Y", "Z", "bracketleft",
  115.     "backslash", "bracketright", "asciicircum", "underscore",
  116.     "grave", "a", "b", "c",
  117.     "d", "e", "f", "g",
  118.     "h", "i", "j", "k",
  119.     "l", "m", "n", "o",
  120.     "p", "q", "r", "s",
  121.     "t", "u", "v", "w",
  122.     "x", "y", "z", "braceleft",
  123.     "bar", "braceright", "asciitilde", "Adieresis",
  124.     "Aring", "Ccedilla", "Eacute", "Ntilde",
  125.     "Odieresis", "Udieresis", "aacute", "agrave",
  126.     "acircumflex", "adieresis", "atilde", "aring",
  127.     "ccedilla", "eacute", "egrave", "ecircumflex",
  128.     "edieresis", "iacute", "igrave", "icircumflex",
  129.     "idieresis", "ntilde", "oacute", "ograve",
  130.     "ocircumflex", "odieresis", "otilde", "uacute",
  131.     "ugrave", "ucircumflex", "udieresis", "dagger",
  132.     "degree", "cent", "sterling", "section",
  133.     "bullet", "paragraph", "germandbls", "registered",
  134.     "copyright", "trademark", "acute", "dieresis",
  135.     "notequal", "AE", "Oslash", "infinity",
  136.     "plusminus", "lessequal", "greaterequal", "yen",
  137.     "mu", "partialdiff", "summation", "product",
  138.     "pi", "integral", "ordfeminine", "ordmasculine",
  139.     "Omega", "ae", "oslash", "questiondown",
  140.     "exclamdown", "logicalnot", "radical", "florin",
  141.     "approxequal", "increment", "guillemotleft", "guillemotright",
  142.     "ellipsis", "nbspace", "Agrave", "Atilde",
  143.     "Otilde", "OE", "oe", "endash",
  144.     "emdash", "quotedblleft", "quotedblright", "quoteleft",
  145.     "quoteright", "divide", "lozenge", "ydieresis",
  146.     "Ydieresis", "fraction", "currency", "guilsinglleft",
  147.     "guilsinglright", "fi", "fl", "daggerdbl",
  148.     "periodcentered", "quotesinglbase", "quotedblbase", "perthousand",
  149.     "Acircumflex", "Ecircumflex", "Aacute", "Edieresis",
  150.     "Egrave", "Iacute", "Icircumflex", "Idieresis",
  151.     "Igrave", "Oacute", "Ocircumflex", "applelogo",
  152.     "Ograve", "Uacute", "Ucircumflex", "Ugrave",
  153.     "dotlessi", "circumflex", "tilde", "macron",
  154.     "breve", "dotaccent", "ring", "cedilla",
  155.     "hungarumlaut", "ogonek", "caron", "Lslash",
  156.     "lslash", "Scaron", "scaron", "Zcaron",
  157.     "zcaron", "brokenbar", "Eth", "eth",
  158.     "Yacute", "yacute", "Thorn", "thorn",
  159.     "minus", "multiply", "onesuperior", "twosuperior",
  160.     "threesuperior", "onehalf", "onequarter", "threequarters",
  161.     "franc", "Gbreve", "gbreve", "Idot",
  162.     "Scedilla", "scedilla", "Cacute", "cacute",
  163.     "Ccaron", "ccaron", "dmacron"
  164. };
  165.  
  166. /* other prototypes */
  167. static void draw_composite_glyf( GLYPH *g, GLYPH *glyph_list, int glyphno, 
  168.     double *matrix, int level);
  169. static void draw_simple_glyf( GLYPH *g, GLYPH *glyph_list, int glyphno, 
  170.     double *matrix);
  171. static double f2dot14( short x);
  172.  
  173. /* get the TTF description table address and length for this index */
  174.  
  175. static void
  176. get_glyf_table(
  177.     int glyphno,
  178.     TTF_GLYF **tab,
  179.     int *len
  180. )
  181. {
  182.     if(tab!=NULL) {
  183.         if (long_offsets) {
  184.             *tab = (TTF_GLYF *) (glyf_start + ntohl(long_loca_table[glyphno]));
  185.         } else {
  186.             *tab = (TTF_GLYF *) (glyf_start + (ntohs(short_loca_table[glyphno]) << 1));
  187.         }
  188.     }
  189.     if(len!=NULL) {
  190.         if (long_offsets) {
  191.             *len = ntohl(long_loca_table[glyphno + 1]) - ntohl(long_loca_table[glyphno]);
  192.         } else {
  193.             *len = (ntohs(short_loca_table[glyphno + 1]) - ntohs(short_loca_table[glyphno])) << 1;
  194.         }
  195.     }
  196. }
  197.  
  198. static void
  199. handle_name(void)
  200. {
  201.     int             j, k, lang, len, platform;
  202.     char           *p, *string_area;
  203.     char           *nbp = name_buffer;
  204.     int             found3 = 0;
  205.  
  206.     string_area = (char *) name_table + ntohs(name_table->offset);
  207.     name_record = &(name_table->nameRecords);
  208.  
  209.     for (j = 0; j < 8; j++) {
  210.         name_fields[j] = ""; 
  211.     }
  212.  
  213.     for (j = 0; j < ntohs(name_table->numberOfNameRecords); j++) {
  214.  
  215.         platform = ntohs(name_record->platformID);
  216.  
  217.         if (platform == 3) {
  218.  
  219.             found3 = 1;
  220.             lang = ntohs(name_record->languageID) & 0xff;
  221.             len = ntohs(name_record->stringLength);
  222.             if (lang == 0 || lang == 9) {
  223.                 k = ntohs(name_record->nameID);
  224.                 if (k < 8) {
  225.                     name_fields[k] = nbp;
  226.  
  227.                     p = string_area + ntohs(name_record->stringOffset);
  228.                     for (k = 0; k < len; k++) {
  229.                         if (p[k] != '\0') {
  230.                             if (p[k] == '(') {
  231.                                 *nbp = '[';
  232.                             } else if (p[k] == ')') {
  233.                                 *nbp = ']';
  234.                             } else {
  235.                                 *nbp = p[k];
  236.                             }
  237.                             nbp++;
  238.                         }
  239.                     }
  240.                     *nbp = '\0';
  241.                     nbp++;
  242.                 }
  243.             }
  244.         }
  245.         name_record++;
  246.     }
  247.  
  248.     string_area = (char *) name_table + ntohs(name_table->offset);
  249.     name_record = &(name_table->nameRecords);
  250.  
  251.     if (!found3) {
  252.         for (j = 0; j < ntohs(name_table->numberOfNameRecords); j++) {
  253.  
  254.             platform = ntohs(name_record->platformID);
  255.  
  256.             if (platform == 1) {
  257.  
  258.                 found3 = 1;
  259.                 lang = ntohs(name_record->languageID) & 0xff;
  260.                 len = ntohs(name_record->stringLength);
  261.                 if (lang == 0 || lang == 9) {
  262.                     k = ntohs(name_record->nameID);
  263.                     if (k < 8) {
  264.                         name_fields[k] = nbp;
  265.  
  266.                         p = string_area + ntohs(name_record->stringOffset);
  267.                         for (k = 0; k < len; k++) {
  268.                             if (p[k] != '\0') {
  269.                                 if (p[k] == '(') {
  270.                                     *nbp = '[';
  271.                                 } else if (p[k] == ')') {
  272.                                     *nbp = ']';
  273.                                 } else {
  274.                                     *nbp = p[k];
  275.                                 }
  276.                                 nbp++;
  277.                             }
  278.                         }
  279.                         *nbp = '\0';
  280.                         nbp++;
  281.                     }
  282.                 }
  283.             }
  284.             name_record++;
  285.         }
  286.     }
  287.     if (!found3) {
  288.         fprintf(stderr, "**** Cannot decode font name fields ****\n");
  289.         exit(1);
  290.     }
  291.     if (name_fields[4][0] == 0) { /* Full Name empty, use Family Name */
  292.         name_fields[4] = name_fields[1];
  293.     }
  294.     if (name_fields[6][0] == 0) { /* Font Name empty, use Full Name */
  295.         name_fields[6] = name_fields[4];
  296.         if (name_fields[6][0] == 0) { /* oops, empty again */
  297.             WARNING_1 fprintf(stderr, "Font name is unknown, setting to \"Unknown\"\n");
  298.             name_fields[6] = "Unknown";
  299.         }
  300.     }
  301.     p = name_fields[6];
  302.     /* must not start with a digit */
  303.     if(isdigit(*p))
  304.         *p+= 'A'-'0'; /* change to a letter */
  305.     while (*p != '\0') {
  306.         if (!isalnum(*p) || *p=='_') {
  307.             *p = '-';
  308.         }
  309.         p++;
  310.     }
  311. }
  312.  
  313. static void
  314. handle_head(void)
  315. {
  316.     long_offsets = ntohs(head_table->indexToLocFormat);
  317.     if (long_offsets != 0 && long_offsets != 1) {
  318.         fprintf(stderr, "**** indexToLocFormat wrong ****\n");
  319.         exit(1);
  320.     }
  321. }
  322.  
  323. /* limit the recursion level to avoid cycles */
  324. #define MAX_COMPOSITE_LEVEL 20
  325.  
  326. static void
  327. draw_composite_glyf(
  328.     GLYPH *g,
  329.     GLYPH *glyph_list,
  330.     int glyphno,
  331.     double *orgmatrix,
  332.     int level
  333. )
  334. {
  335.     int len;
  336.     short           ncontours;
  337.     USHORT          flagbyte, glyphindex;
  338.     double          arg1, arg2;
  339.     BYTE           *ptr;
  340.     char           *bptr;
  341.     SHORT          *sptr;
  342.     double          matrix[6], newmatrix[6];
  343.  
  344.     get_glyf_table(glyphno, &glyf_table, &len);
  345.  
  346.     if(len<=0) /* nothing to do */
  347.         return;
  348.  
  349.     ncontours = ntohs(glyf_table->numberOfContours);
  350.     if (ncontours >= 0) { /* simple case */
  351.         draw_simple_glyf(g, glyph_list, glyphno, orgmatrix);
  352.         return;
  353.     }
  354.  
  355.     if(ISDBG(COMPOSITE) && level ==0)
  356.         fprintf(stderr, "* %s [ %.2f %.2f %.2f %.2f %.2f %.2f ]\n", g->name,
  357.             orgmatrix[0], orgmatrix[1], orgmatrix[2], orgmatrix[3],
  358.             orgmatrix[4], orgmatrix[5]);
  359.  
  360.     /* complex case */
  361.     if(level >= MAX_COMPOSITE_LEVEL) {
  362.         WARNING_1 fprintf(stderr, 
  363.             "*** Glyph %s: stopped (possibly infinite) recursion at depth %d\n",
  364.             g->name, level);
  365.         return;
  366.     }
  367.  
  368.     ptr = ((BYTE *) glyf_table + sizeof(TTF_GLYF));
  369.     sptr = (SHORT *) ptr;
  370.     do {
  371.         flagbyte = ntohs(*sptr);
  372.         sptr++;
  373.         glyphindex = ntohs(*sptr);
  374.         sptr++;
  375.  
  376.         if (flagbyte & ARG_1_AND_2_ARE_WORDS) {
  377.             arg1 = (short)ntohs(*sptr);
  378.             sptr++;
  379.             arg2 = (short)ntohs(*sptr);
  380.             sptr++;
  381.         } else {
  382.             bptr = (char *) sptr;
  383.             arg1 = (signed char) bptr[0];
  384.             arg2 = (signed char) bptr[1];
  385.             sptr++;
  386.         }
  387.         matrix[1] = matrix[2] = 0.0;
  388.  
  389.         if (flagbyte & WE_HAVE_A_SCALE) {
  390.             matrix[0] = matrix[3] = f2dot14(*sptr);
  391.             sptr++;
  392.         } else if (flagbyte & WE_HAVE_AN_X_AND_Y_SCALE) {
  393.             matrix[0] = f2dot14(*sptr);
  394.             sptr++;
  395.             matrix[3] = f2dot14(*sptr);
  396.             sptr++;
  397.         } else if (flagbyte & WE_HAVE_A_TWO_BY_TWO) {
  398.             matrix[0] = f2dot14(*sptr);
  399.             sptr++;
  400.             matrix[1] = f2dot14(*sptr);
  401.             sptr++;
  402.             matrix[2] = f2dot14(*sptr);
  403.             sptr++;
  404.             matrix[3] = f2dot14(*sptr);
  405.             sptr++;
  406.         } else {
  407.             matrix[0] = matrix[3] = 1.0;
  408.         }
  409.  
  410.         /*
  411.          * See *
  412.          * http://fonts.apple.com/TTRefMan/RM06/Chap6g
  413.          * lyf.html * matrix[0,1,2,3,4,5]=a,b,c,d,m,n
  414.          */
  415.  
  416.         if (fabs(matrix[0]) > fabs(matrix[1]))
  417.             matrix[4] = fabs(matrix[0]);
  418.         else
  419.             matrix[4] = fabs(matrix[1]);
  420.         if (fabs(fabs(matrix[0]) - fabs(matrix[2])) <= 33. / 65536.)
  421.             matrix[4] *= 2.0;
  422.  
  423.         if (fabs(matrix[2]) > fabs(matrix[3]))
  424.             matrix[5] = fabs(matrix[2]);
  425.         else
  426.             matrix[5] = fabs(matrix[3]);
  427.         if (fabs(fabs(matrix[2]) - fabs(matrix[3])) <= 33. / 65536.)
  428.             matrix[5] *= 2.0;
  429.  
  430.         /*
  431.          * fprintf (stderr,"Matrix Opp %hd
  432.          * %hd\n",arg1,arg2);
  433.          */
  434. #if 0
  435.         fprintf(stderr, "Matrix: %f %f %f %f %f %f\n",
  436.          matrix[0], matrix[1], matrix[2], matrix[3],
  437.             matrix[4], matrix[5]);
  438.         fprintf(stderr, "Offset: %f %f (%s)\n",
  439.             arg1, arg2,
  440.             ((flagbyte & ARGS_ARE_XY_VALUES) ? "XY" : "index"));
  441. #endif
  442.  
  443.         if (flagbyte & ARGS_ARE_XY_VALUES) {
  444.             matrix[4] *= arg1;
  445.             matrix[5] *= arg2;
  446.         } else {
  447.             WARNING_1 fprintf(stderr, 
  448.                 "*** Glyph %s: reusing scale from another glyph is unsupported\n",
  449.                 g->name);
  450.             /*
  451.              * must extract values from a glyph
  452.              * but it seems to be too much pain
  453.              * and it's not clear now that it
  454.              * would be really used in any
  455.              * interesting font
  456.              */
  457.         }
  458.  
  459.         /* at this point arg1,arg2 contain what logically should be matrix[4,5] */
  460.  
  461.         /* combine matrices */
  462.  
  463.         newmatrix[0] = orgmatrix[0]*matrix[0] + orgmatrix[2]*matrix[1];
  464.         newmatrix[1] = orgmatrix[0]*matrix[2] + orgmatrix[2]*matrix[3];
  465.  
  466.         newmatrix[2] = orgmatrix[1]*matrix[0] + orgmatrix[3]*matrix[1];
  467.         newmatrix[3] = orgmatrix[1]*matrix[2] + orgmatrix[3]*matrix[3];
  468.  
  469.         newmatrix[4] = orgmatrix[0]*matrix[4] + orgmatrix[2]*matrix[5] + orgmatrix[4];
  470.         newmatrix[5] = orgmatrix[1]*matrix[4] + orgmatrix[3]*matrix[5] + orgmatrix[5];
  471.  
  472.         if(ISDBG(COMPOSITE)) {
  473.             fprintf(stderr, "%*c+-> %2d %s [ %.2f %.2f %.2f %.2f %.2f %.2f ]\n",
  474.                 level+1, ' ', level, glyph_list[glyphindex].name,
  475.                 matrix[0], matrix[1], matrix[2], matrix[3],
  476.                 matrix[4], matrix[5]);
  477.             fprintf(stderr, "%*c        = [ %.2f %.2f %.2f %.2f %.2f %.2f ]\n",
  478.                 level+1, ' ',
  479.                 newmatrix[0], newmatrix[1], newmatrix[2], newmatrix[3],
  480.                 newmatrix[4], newmatrix[5]);
  481.         }
  482.         draw_composite_glyf(g, glyph_list, glyphindex, newmatrix, level+1);
  483.  
  484.     } while (flagbyte & MORE_COMPONENTS);
  485. }
  486.  
  487. static void
  488. draw_simple_glyf(
  489.     GLYPH *g,
  490.     GLYPH *glyph_list,
  491.     int glyphno,
  492.     double *matrix
  493. )
  494. {
  495.     int             i, j, k, k1, len, first, cs, ce;
  496.     /* We assume that hsbw always sets to(0, 0) */
  497.     double          xlast = 0, ylast = 0;
  498.     int             finished, nguide, contour_start, contour_end;
  499.     short           ncontours, n_inst, last_point;
  500.     USHORT         *contour_end_pt;
  501.     BYTE           *ptr;
  502. #define GLYFSZ    2000
  503.     short           xabs[GLYFSZ], yabs[GLYFSZ], xrel[GLYFSZ], yrel[GLYFSZ];
  504.     double          xcoord[GLYFSZ], ycoord[GLYFSZ];
  505.     BYTE            flags[GLYFSZ];
  506.     double          tx, ty;
  507.     int             needreverse = 0;    /* transformation may require
  508.                          * that */
  509.     GENTRY         *lge;
  510.  
  511.     lge = g->lastentry;
  512.  
  513.     get_glyf_table(glyphno, &glyf_table, &len);
  514.  
  515.     if (len <= 0) {
  516.         WARNING_1 fprintf(stderr,
  517.             "**** Composite glyph %s refers to non-existent glyph %s, ignored\n",
  518.             g->name,
  519.             glyph_list[glyphno].name);
  520.         return;
  521.     }
  522.     ncontours = ntohs(glyf_table->numberOfContours);
  523.     if (ncontours < 0) {
  524.         WARNING_1 fprintf(stderr,
  525.             "**** Composite glyph %s refers to composite glyph %s, ignored\n",
  526.             g->name,
  527.             glyph_list[glyphno].name);
  528.         return;
  529.     }
  530.     contour_end_pt = (USHORT *) ((char *) glyf_table + sizeof(TTF_GLYF));
  531.  
  532.     last_point = ntohs(contour_end_pt[ncontours - 1]);
  533.     n_inst = ntohs(contour_end_pt[ncontours]);
  534.  
  535.     ptr = ((BYTE *) contour_end_pt) + (ncontours << 1) + n_inst + 2;
  536.     j = k = 0;
  537.     while (k <= last_point) {
  538.         flags[k] = ptr[j];
  539.  
  540.         if (ptr[j] & REPEAT) {
  541.             for (k1 = 0; k1 < ptr[j + 1]; k1++) {
  542.                 k++;
  543.                 flags[k] = ptr[j];
  544.             }
  545.             j++;
  546.         }
  547.         j++;
  548.         k++;
  549.     }
  550.  
  551.     for (k = 0; k <= last_point; k++) {
  552.         if (flags[k] & XSHORT) {
  553.             if (flags[k] & XSAME) {
  554.                 xrel[k] = ptr[j];
  555.             } else {
  556.                 xrel[k] = -ptr[j];
  557.             }
  558.             j++;
  559.         } else if (flags[k] & XSAME) {
  560.             xrel[k] = 0.0;
  561.         } else {
  562.             xrel[k] = (short)( ptr[j] * 256 + ptr[j + 1] );
  563.             j += 2;
  564.         }
  565.         if (k == 0) {
  566.             xabs[k] = xrel[k];
  567.         } else {
  568.             xabs[k] = xrel[k] + xabs[k - 1];
  569.         }
  570.  
  571.     }
  572.  
  573.     for (k = 0; k <= last_point; k++) {
  574.         if (flags[k] & YSHORT) {
  575.             if (flags[k] & YSAME) {
  576.                 yrel[k] = ptr[j];
  577.             } else {
  578.                 yrel[k] = -ptr[j];
  579.             }
  580.             j++;
  581.         } else if (flags[k] & YSAME) {
  582.             yrel[k] = 0;
  583.         } else {
  584.             yrel[k] = ptr[j] * 256 + ptr[j + 1];
  585.             j += 2;
  586.         }
  587.         if (k == 0) {
  588.             yabs[k] = yrel[k];
  589.         } else {
  590.             yabs[k] = yrel[k] + yabs[k - 1];
  591.         }
  592.     }
  593.  
  594.     if (matrix) {
  595.         for (i = 0; i <= last_point; i++) {
  596.             tx = xabs[i];
  597.             ty = yabs[i];
  598.             xcoord[i] = fscale(matrix[0] * tx + matrix[2] * ty + matrix[4]);
  599.             ycoord[i] = fscale(matrix[1] * tx + matrix[3] * ty + matrix[5]);
  600.         }
  601.     } else {
  602.         for (i = 0; i <= last_point; i++) {
  603.             xcoord[i] = fscale(xabs[i]);
  604.             ycoord[i] = fscale(yabs[i]);
  605.         }
  606.     }
  607.  
  608.     i = j = 0;
  609.     first = 1;
  610.  
  611.     while (i <= ntohs(contour_end_pt[ncontours - 1])) {
  612.         contour_end = ntohs(contour_end_pt[j]);
  613.  
  614.         if (first) {
  615.             fg_rmoveto(g, xcoord[i], ycoord[i]);
  616.             xlast = xcoord[i];
  617.             ylast = ycoord[i];
  618.             contour_start = i;
  619.             first = 0;
  620.         } else if (flags[i] & ONOROFF) {
  621.             fg_rlineto(g, xcoord[i], ycoord[i]);
  622.             xlast = xcoord[i];
  623.             ylast = ycoord[i];
  624.         } else {
  625.             cs = i - 1;
  626.             finished = nguide = 0;
  627.             while (!finished) {
  628.                 if (i == contour_end + 1) {
  629.                     ce = contour_start;
  630.                     finished = 1;
  631.                 } else if (flags[i] & ONOROFF) {
  632.                     ce = i;
  633.                     finished = 1;
  634.                 } else {
  635.                     i++;
  636.                     nguide++;
  637.                 }
  638.             }
  639.  
  640.             switch (nguide) {
  641.             case 0:
  642.                 fg_rlineto(g, xcoord[ce], ycoord[ce]);
  643.                 xlast = xcoord[ce];
  644.                 ylast = ycoord[ce];
  645.                 break;
  646.  
  647.             case 1:
  648.                 fg_rrcurveto(g,
  649.                       (xcoord[cs] + 2.0 * xcoord[cs + 1]) / 3.0,
  650.                       (ycoord[cs] + 2.0 * ycoord[cs + 1]) / 3.0,
  651.                       (2.0 * xcoord[cs + 1] + xcoord[ce]) / 3.0,
  652.                       (2.0 * ycoord[cs + 1] + ycoord[ce]) / 3.0,
  653.                         xcoord[ce],
  654.                         ycoord[ce]
  655.                     );
  656.                 xlast = xcoord[ce];
  657.                 ylast = ycoord[ce];
  658.  
  659.                 break;
  660.  
  661.             case 2:
  662.                 fg_rrcurveto(g,
  663.                      (-xcoord[cs] + 4.0 * xcoord[cs + 1]) / 3.0,
  664.                      (-ycoord[cs] + 4.0 * ycoord[cs + 1]) / 3.0,
  665.                       (4.0 * xcoord[cs + 2] - xcoord[ce]) / 3.0,
  666.                       (4.0 * ycoord[cs + 2] - ycoord[ce]) / 3.0,
  667.                         xcoord[ce],
  668.                         ycoord[ce]
  669.                     );
  670.                 xlast = xcoord[ce];
  671.                 ylast = ycoord[ce];
  672.                 break;
  673.  
  674.             case 3:
  675.                 fg_rrcurveto(g,
  676.                       (xcoord[cs] + 2.0 * xcoord[cs + 1]) / 3.0,
  677.                       (ycoord[cs] + 2.0 * ycoord[cs + 1]) / 3.0,
  678.                   (5.0 * xcoord[cs + 1] + xcoord[cs + 2]) / 6.0,
  679.                   (5.0 * ycoord[cs + 1] + ycoord[cs + 2]) / 6.0,
  680.                       (xcoord[cs + 1] + xcoord[cs + 2]) / 2.0,
  681.                       (ycoord[cs + 1] + ycoord[cs + 2]) / 2.0
  682.                     );
  683.  
  684.                 fg_rrcurveto(g,
  685.                   (xcoord[cs + 1] + 5.0 * xcoord[cs + 2]) / 6.0,
  686.                   (ycoord[cs + 1] + 5.0 * ycoord[cs + 2]) / 6.0,
  687.                   (5.0 * xcoord[cs + 2] + xcoord[cs + 3]) / 6.0,
  688.                   (5.0 * ycoord[cs + 2] + ycoord[cs + 3]) / 6.0,
  689.                       (xcoord[cs + 3] + xcoord[cs + 2]) / 2.0,
  690.                       (ycoord[cs + 3] + ycoord[cs + 2]) / 2.0
  691.                     );
  692.  
  693.                 fg_rrcurveto(g,
  694.                   (xcoord[cs + 2] + 5.0 * xcoord[cs + 3]) / 6.0,
  695.                   (ycoord[cs + 2] + 5.0 * ycoord[cs + 3]) / 6.0,
  696.                       (2.0 * xcoord[cs + 3] + xcoord[ce]) / 3.0,
  697.                       (2.0 * ycoord[cs + 3] + ycoord[ce]) / 3.0,
  698.                         xcoord[ce],
  699.                         ycoord[ce]
  700.                     );
  701.                 ylast = ycoord[ce];
  702.                 xlast = xcoord[ce];
  703.  
  704.                 break;
  705.  
  706.             default:
  707.                 k1 = cs + nguide;
  708.                 fg_rrcurveto(g,
  709.                       (xcoord[cs] + 2.0 * xcoord[cs + 1]) / 3.0,
  710.                       (ycoord[cs] + 2.0 * ycoord[cs + 1]) / 3.0,
  711.                   (5.0 * xcoord[cs + 1] + xcoord[cs + 2]) / 6.0,
  712.                   (5.0 * ycoord[cs + 1] + ycoord[cs + 2]) / 6.0,
  713.                       (xcoord[cs + 1] + xcoord[cs + 2]) / 2.0,
  714.                       (ycoord[cs + 1] + ycoord[cs + 2]) / 2.0
  715.                     );
  716.  
  717.                 for (k = cs + 2; k <= k1 - 1; k++) {
  718.                     fg_rrcurveto(g,
  719.                     (xcoord[k - 1] + 5.0 * xcoord[k]) / 6.0,
  720.                     (ycoord[k - 1] + 5.0 * ycoord[k]) / 6.0,
  721.                     (5.0 * xcoord[k] + xcoord[k + 1]) / 6.0,
  722.                     (5.0 * ycoord[k] + ycoord[k + 1]) / 6.0,
  723.                         (xcoord[k] + xcoord[k + 1]) / 2.0,
  724.                          (ycoord[k] + ycoord[k + 1]) / 2.0
  725.                         );
  726.  
  727.                 }
  728.  
  729.                 fg_rrcurveto(g,
  730.                       (xcoord[k1 - 1] + 5.0 * xcoord[k1]) / 6.0,
  731.                       (ycoord[k1 - 1] + 5.0 * ycoord[k1]) / 6.0,
  732.                       (2.0 * xcoord[k1] + xcoord[ce]) / 3.0,
  733.                       (2.0 * ycoord[k1] + ycoord[ce]) / 3.0,
  734.                         xcoord[ce],
  735.                         ycoord[ce]
  736.                     );
  737.                 xlast = xcoord[ce];
  738.                 ylast = ycoord[ce];
  739.  
  740.                 break;
  741.             }
  742.         }
  743.         if (i >= contour_end) {
  744.             g_closepath(g);
  745.             first = 1;
  746.             i = contour_end + 1;
  747.             j++;
  748.         } else {
  749.             i++;
  750.         }
  751.     }
  752.  
  753.     if (matrix) {
  754.         /* guess whether do we need to reverse the results */
  755.  
  756.         double             x[3], y[3];
  757.         int                max = 0, from, to;
  758.  
  759.         /* transform a triangle going in proper direction */
  760.         /*
  761.          * the origin of triangle is in (0,0) so we know it in
  762.          * advance
  763.          */
  764.  
  765.         x[0] = y[0] = 0;
  766.         x[1] = matrix[0] * 0 + matrix[2] * 300;
  767.         y[1] = matrix[1] * 0 + matrix[3] * 300;
  768.         x[2] = matrix[0] * 300 + matrix[2] * 0;
  769.         y[2] = matrix[1] * 300 + matrix[3] * 0;
  770.  
  771.         /* then find the topmost point */
  772.         for (i = 0; i < 3; i++)
  773.             if (y[i] > y[max])
  774.                 max = i;
  775.         from = (max + 3 - 1) % 3;
  776.         to = (max + 1) % 3;
  777.  
  778.         needreverse = 0;
  779.  
  780.         /* special cases for horizontal lines */
  781.         if (y[max] == y[from]) {
  782.             if (x[max] < y[from])
  783.                 needreverse = 1;
  784.         } else if (y[to] == y[from]) {
  785.             if (x[to] < x[max])
  786.                 needreverse = 1;
  787.         } else {    /* generic case */
  788.             if ((x[to] - x[max]) * (y[max] - y[from])
  789.                 > (x[max] - x[from]) * (y[to] - y[max]))
  790.                 needreverse = 1;
  791.         }
  792.  
  793.         if (needreverse) {
  794.             if (lge) {
  795.                 assertpath(lge->next, __FILE__, __LINE__, g->name);
  796.                 reversepathsfromto(lge->next, NULL);
  797.             } else {
  798.                 assertpath(g->entries, __FILE__, __LINE__, g->name);
  799.                 reversepaths(g);
  800.             }
  801.         }
  802.     }
  803. }
  804.  
  805. static double
  806. f2dot14(
  807.     short x
  808. )
  809. {
  810.     short           y = ntohs(x);
  811.     return (y >> 14) + ((y & 0x3fff) / 16384.0);
  812. }
  813.  
  814.  
  815. /* check that the pointer points within the file */
  816. /* returns 0 if pointer is good, 1 if bad */
  817. static int
  818. badpointer(
  819.     void *ptr
  820. )
  821. {
  822.     return (ptr < (void *)filebuffer || ptr >= (void *)filebuffer_end);
  823. }
  824.  
  825. /*
  826.  * Externally accessible methods
  827.  */
  828.  
  829. /*
  830.  * Open font and prepare to return information to the main driver.
  831.  * May print error and warning messages.
  832.  * Exit on error.
  833.  */
  834.  
  835. static void
  836. openfont(
  837.     char *fname,
  838.     char *arg /* unused now */
  839. )
  840. {
  841.     int             i, j;
  842.     struct stat     statbuf;
  843.     static struct {
  844.         void **tbpp; /* pointer to pointer to the table */
  845.         char name[5]; /* table name */
  846.         char optional; /* flag: table may be missing */
  847.     } tables[] = {
  848.         { (void **)&name_table, "name", 0 },
  849.         { (void **)&head_table, "head", 0 },
  850.         { (void **)&hhea_table, "hhea", 0 },
  851.         { (void **)&post_table, "post", 0 },
  852.         { (void **)&glyf_start, "glyf", 0 },
  853.         { (void **)&cmap_table, "cmap", 0 },
  854.         { (void **)&kern_table, "kern", 1 },
  855.         { (void **)&maxp_table, "maxp", 0 },
  856.         { (void **)&hmtx_table, "hmtx", 0 },
  857.         { (void **)&long_loca_table, "loca", 0 },
  858.         { NULL, "", 0 } /* end of table */
  859.     };
  860.  
  861.     if (stat(fname, &statbuf) == -1) {
  862.         fprintf(stderr, "**** Cannot access %s ****\n", fname);
  863.         exit(1);
  864.     }
  865.     if ((filebuffer = malloc(statbuf.st_size)) == NULL) {
  866.         fprintf(stderr, "**** Cannot malloc space for file ****\n");
  867.         exit(1);
  868.     }
  869.  
  870.     filebuffer_end = filebuffer + statbuf.st_size;
  871.  
  872.     if ((ttf_file = fopen(fname, "rb")) == NULL) {
  873.         fprintf(stderr, "**** Cannot open file '%s'\n", fname);
  874.         exit(1);
  875.     } else {
  876.         WARNING_2 fprintf(stderr, "Processing file %s\n", fname);
  877.     }
  878.  
  879.     if (fread(filebuffer, 1, statbuf.st_size, ttf_file) != statbuf.st_size) {
  880.         fprintf(stderr, "**** Could not read whole file \n");
  881.         exit(1);
  882.     }
  883.     fclose(ttf_file);
  884.  
  885.     directory = (TTF_DIRECTORY *) filebuffer;
  886.  
  887.     if (ntohl(directory->sfntVersion) != 0x00010000) {
  888.         fprintf(stderr,
  889.             "**** Unknown File Version number [%x], or not a TrueType file\n",
  890.             directory->sfntVersion);
  891.         exit(1);
  892.     }
  893.  
  894.     /* clear the tables */
  895.     for(j=0; tables[j].tbpp != NULL; j++)
  896.         *(tables[j].tbpp) = NULL;
  897.  
  898.     dir_entry = &(directory->list);
  899.  
  900.     for (i = 0; i < ntohs(directory->numTables); i++) {
  901.  
  902.         for(j=0; tables[j].tbpp != NULL; j++)
  903.             if (memcmp(dir_entry->tag, tables[j].name, 4) == 0) {
  904.                 *(tables[j].tbpp) = (void *) (filebuffer + ntohl(dir_entry->offset));
  905.                 break;
  906.             }
  907.  
  908.         if (memcmp(dir_entry->tag, "EBDT", 4) == 0 ||
  909.                memcmp(dir_entry->tag, "EBLC", 4) == 0 ||
  910.                memcmp(dir_entry->tag, "EBSC", 4) == 0) {
  911.             WARNING_1 fprintf(stderr, "Font contains bitmaps\n");
  912.         }
  913.         dir_entry++;
  914.     }
  915.  
  916.     for(j=0; tables[j].tbpp != NULL; j++)
  917.         if(!tables[j].optional && badpointer( *(tables[j].tbpp) )) {
  918.             fprintf(stderr, "**** File contains no required table '%s'\n", tables[j].name);
  919.             exit(1);
  920.         }
  921.  
  922.     handle_name();
  923.  
  924.     handle_head();
  925.  
  926.     ttf_nglyphs = ntohs(maxp_table->numGlyphs);
  927.  
  928.     enc_found_ms = enc_found_mac = 0;
  929. }
  930.  
  931. /*
  932.  * Close font.
  933.  * Exit on error.
  934.  */
  935.  
  936. static void
  937. closefont(
  938.     void
  939. )
  940. {
  941.     return; /* empty operation */
  942. }
  943.  
  944. /*
  945.  * Get the number of glyphs in font.
  946.  */
  947.  
  948. static int
  949. getnglyphs (
  950.     void
  951. )
  952. {
  953.     return ttf_nglyphs;
  954. }
  955.  
  956. /*
  957.  * Get the names of the glyphs.
  958.  * Returns 0 if the names were assigned, non-zero if the font
  959.  * provides no glyph names.
  960.  */
  961.  
  962. static int
  963. glnames(
  964.     GLYPH *glyph_list
  965. )
  966. {
  967.     int             i, len, n, npost;
  968.     unsigned int    format;
  969.     USHORT         *name_index;
  970.     char           *ptr, *p;
  971.     char          **ps_name_ptr = (char **) malloc(ttf_nglyphs * sizeof(char *));
  972.     int             n_ps_names;
  973.     int             ps_fmt_3 = 0;
  974.  
  975.     format = ntohl(post_table->formatType);
  976.  
  977.     if (format == 0x00010000) {
  978.         for (i = 0; i < 258 && i < ttf_nglyphs; i++) {
  979.             glyph_list[i].name = mac_glyph_names[i];
  980.         }
  981.     } else if (format == 0x00020000) {
  982.                 npost = ntohs(post_table->numGlyphs);
  983.                 if (ttf_nglyphs != npost) {
  984.                         /* This is an error in the font, but we can now cope */
  985.                         WARNING_1 fprintf(stderr, "**** Postscript table size mismatch %d/%d ****\n",
  986.                                 npost, ttf_nglyphs);
  987.                 }
  988.                 n_ps_names = 0;
  989.                 name_index = &(post_table->glyphNameIndex);
  990.  
  991.                 /* This checks the integrity of the post table */       
  992.                 for (i=0; i<npost; i++) {
  993.                     n = ntohs(name_index[i]);
  994.                     if (n > n_ps_names + 257) {
  995.                         n_ps_names = n - 257;
  996.                     }
  997.                 }
  998.  
  999.                 ptr = (char *) post_table + 34 + (ttf_nglyphs << 1);
  1000.                 i = 0;
  1001.                 while (*ptr > 0 && i < n_ps_names) {
  1002.                         len = *ptr;
  1003.                         /* previously the program wrote nulls into the table. If the table
  1004.                            was corrupt, this could put zeroes anywhere, leading to obscure bugs,
  1005.                            so now I malloc space for the names. Yes it is much less efficient */
  1006.                            
  1007.                         if ((p = malloc(len+1)) == NULL) {
  1008.                             fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__);
  1009.                             exit(255);
  1010.                         }
  1011.                         
  1012.                         ps_name_ptr[i] = p;
  1013.                         strncpy(p, ptr+1, len);
  1014.                         p[len] = '\0';
  1015.                         i ++;
  1016.                         ptr += len + 1;
  1017.                 }
  1018.         
  1019.                 if (i != n_ps_names)
  1020.                 {
  1021.                     WARNING_2 fprintf (stderr, "** Postscript Name mismatch %d != %d **\n",
  1022.                              i, n_ps_names);
  1023.                     n_ps_names = i;
  1024.                 }
  1025.  
  1026.                 /*
  1027.                  * for (i=0; i<n_ps_names; i++) { fprintf(stderr, "i=%d,
  1028.                  * len=%d, name=%s\n", i, ps_name_len[i], ps_name_ptr[i]); }
  1029.                  */
  1030.  
  1031.                 for (i = 0; i < npost; i++) {
  1032.                         n = ntohs(name_index[i]);
  1033.                         if (n < 258) {
  1034.                                 glyph_list[i].name = mac_glyph_names[n];
  1035.                         } else if (n < 258 + n_ps_names) {
  1036.                                 glyph_list[i].name = ps_name_ptr[n - 258];
  1037.                         } else {
  1038.                                 glyph_list[i].name = malloc(10);
  1039.                                 sprintf(glyph_list[i].name, "_%d", n);
  1040.                                 WARNING_2 fprintf(stderr,
  1041.                                         "**** Glyph No. %d has no postscript name, becomes %s ****\n",
  1042.                                         i, glyph_list[i].name);
  1043.                         }
  1044.                 }
  1045.                 /* Now fake postscript names for all those beyond the end of the table */
  1046.                 if (npost < ttf_nglyphs) {
  1047.                     for (i=npost; i<ttf_nglyphs; i++) {
  1048.                         if ((glyph_list[i].name = malloc(10)) == NULL)
  1049.                         {
  1050.                             fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__);
  1051.                             exit(255);
  1052.                         }
  1053.                         sprintf(glyph_list[i].name, "_%d", i);
  1054.                         WARNING_2 fprintf(stderr,
  1055.                                 "** Glyph No. %d has no postscript name, becomes %s **\n",
  1056.                                 i, glyph_list[i].name);
  1057.                     }
  1058.                 }
  1059.     } else if (format == 0x00030000) {
  1060.         WARNING_3 fputs("No postscript table, using default\n", stderr);
  1061.         ps_fmt_3 = 1;
  1062.     } else if (format == 0x00028000) {
  1063.         ptr = (char *) &(post_table->numGlyphs);
  1064.         for (i = 0; i < ttf_nglyphs; i++) {
  1065.             glyph_list[i].name = mac_glyph_names[i + ptr[i]];
  1066.         }
  1067.     } else {
  1068.         fprintf(stderr,
  1069.             "**** Postscript table in wrong format %x ****\n",
  1070.             format);
  1071.         exit(1);
  1072.     }
  1073.  
  1074.     return ps_fmt_3;
  1075. }
  1076.  
  1077. /*
  1078.  * Get the metrics of the glyphs.
  1079.  */
  1080.  
  1081. static void
  1082. glmetrics(
  1083.     GLYPH *glyph_list
  1084. )
  1085. {
  1086.     int             i;
  1087.     int             n_hmetrics = ntohs(hhea_table->numberOfHMetrics);
  1088.     GLYPH          *g;
  1089.     LONGHORMETRIC  *hmtx_entry = hmtx_table;
  1090.     FWORD          *lsblist;
  1091.  
  1092.     for (i = 0; i < n_hmetrics; i++) {
  1093.         g = &(glyph_list[i]);
  1094.         g->width = ntohs(hmtx_entry->advanceWidth);
  1095.         g->lsb = ntohs(hmtx_entry->lsb);
  1096.         hmtx_entry++;
  1097.     }
  1098.  
  1099.     lsblist = (FWORD *) hmtx_entry;
  1100.     hmtx_entry--;
  1101.  
  1102.     for (i = n_hmetrics; i < ttf_nglyphs; i++) {
  1103.         g = &(glyph_list[i]);
  1104.         g->width = ntohs(hmtx_entry->advanceWidth);
  1105.         g->lsb = ntohs(lsblist[i - n_hmetrics]);
  1106.     }
  1107.  
  1108.     for (i = 0; i < ttf_nglyphs; i++) {
  1109.         g = &(glyph_list[i]);
  1110.         get_glyf_table(i, &glyf_table, &g->ttf_pathlen);
  1111.  
  1112.         g->xMin = (short)ntohs(glyf_table->xMin);
  1113.         g->xMax = (short)ntohs(glyf_table->xMax);
  1114.         g->yMin = (short)ntohs(glyf_table->yMin);
  1115.         g->yMax = (short)ntohs(glyf_table->yMax);
  1116.     }
  1117.  
  1118. }
  1119.  
  1120.  
  1121. static void
  1122. handle_ms_encoding(
  1123.     GLYPH *glyph_list,
  1124.     int *encoding,
  1125.     int *unimap
  1126. )
  1127. {
  1128.     int             j, k, kk, set_ok;
  1129.     USHORT          start, end, ro;
  1130.     short           delta, n;
  1131.  
  1132.     for (j = 0; j < cmap_n_segs - 1; j++) {
  1133.         start = ntohs(cmap_seg_start[j]);
  1134.         end = ntohs(cmap_seg_end[j]);
  1135.         delta = ntohs(cmap_idDelta[j]);
  1136.         ro = ntohs(cmap_idRangeOffset[j]);
  1137.  
  1138.         for (k = start; k <= end; k++) {
  1139.             if (ro == 0) {
  1140.                 n = k + delta;
  1141.             } else {
  1142.                 n = ntohs(*((ro >> 1) + (k - start) +
  1143.                  &(cmap_idRangeOffset[j])));
  1144.                 if (delta != 0)
  1145.                 {
  1146.                     /*  Not exactly sure how to deal with this circumstance,
  1147.                         I suspect it never occurs */
  1148.                     n += delta;
  1149.                     fprintf (stderr,
  1150.                          "rangeoffset and delta both non-zero - %d/%d",
  1151.                          ro, delta);
  1152.                 }
  1153.             }
  1154.             if(n<0 || n>=ttf_nglyphs) {
  1155.                 WARNING_1 fprintf(stderr, "Font contains a broken glyph code mapping, ignored\n");
  1156.                 continue;
  1157.             }
  1158.             if (glyph_list[n].orig_code != -1) {
  1159. #if 0
  1160.                 if (strcmp(glyph_list[n].name, ".notdef") != 0) {
  1161.                     WARNING_2 fprintf(stderr,
  1162.                         "Glyph %s has >= two encodings (A), %4.4x & %4.4x\n",
  1163.                      glyph_list[n].name,
  1164.                         glyph_list[n].orig_code,
  1165.                         k);
  1166.                 }
  1167. #endif
  1168.                 set_ok = 0;
  1169.             } else {
  1170.                 set_ok = 1;
  1171.             }
  1172.             if (enc_type==1 || forcemap) {
  1173.                 kk = unicode_rev_lookup(k);
  1174.                 if(ISDBG(UNICODE))
  1175.                     fprintf(stderr, "Unicode %s - 0x%04x\n",glyph_list[n].name,k);
  1176.                 if (set_ok) {
  1177.                     glyph_list[n].orig_code = k;
  1178.                     /* glyph_list[n].char_no = kk; */
  1179.                 }
  1180.                 if (kk >= 0 && kk < ENCTABSZ && encoding[kk] == -1)
  1181.                     encoding[kk] = n;
  1182.             } else {
  1183.                 if ((k & 0xff00) == 0xf000) {
  1184.                     if( encoding[k & 0x00ff] == -1 ) {
  1185.                         encoding[k & 0x00ff] = n;
  1186.                         if (set_ok) {
  1187.                             /* glyph_list[n].char_no = k & 0x00ff; */
  1188.                             glyph_list[n].orig_code = k;
  1189.                         }
  1190.                     }
  1191.                 } else {
  1192.                     if (set_ok) {
  1193.                         /* glyph_list[n].char_no = k; */
  1194.                         glyph_list[n].orig_code = k;
  1195.                     }
  1196.                     WARNING_2 fprintf(stderr,
  1197.                         "Glyph %s has non-symbol encoding %4.4x\n",
  1198.                      glyph_list[n].name,
  1199.                         k & 0xffff);
  1200.                     /*
  1201.                      * just use the code
  1202.                      * as it is
  1203.                      */
  1204.                     if ((k & ~0xff) == 0 && encoding[k] == -1 )
  1205.                         encoding[k] = n;
  1206.                 }
  1207.             }
  1208.         }
  1209.     }
  1210. }
  1211.  
  1212. static void
  1213. handle_mac_encoding(
  1214.     GLYPH *glyph_list,
  1215.     int *encoding,
  1216.     int *unimap
  1217. )
  1218. {
  1219.     short           n;
  1220.     int             j, size;
  1221.  
  1222.     size = ntohs(encoding0->length) - 6;
  1223.     for (j = 0; j < size; j++) {
  1224.         n = encoding0->glyphIdArray[j];
  1225.         if (glyph_list[n].char_no != -1) {
  1226.             WARNING_2 fprintf(stderr,
  1227.                 "Glyph %s has >= two encodings (B), %4.4x & %4.4x\n",
  1228.                 glyph_list[n].name,
  1229.                   glyph_list[n].char_no,
  1230.                 j);
  1231.         } else {
  1232.             if (j < ENCTABSZ) {
  1233.                 if(encoding[j] == -1) {
  1234.                     glyph_list[n].char_no = j;
  1235.                     encoding[j] = n;
  1236.                 }
  1237.             }
  1238.         }
  1239.     }
  1240. }
  1241.  
  1242. /*
  1243.  * Get the original encoding of the font. 
  1244.  * Returns 1 for if the original encoding is Unicode, 2 if the
  1245.  * original encoding is other 16-bit, 0 if 8-bit.
  1246.  */
  1247.  
  1248. static int
  1249. glenc(
  1250.     GLYPH *glyph_list,
  1251.     int *encoding,
  1252.     int *unimap
  1253. )
  1254. {
  1255.     int             num_tables = ntohs(cmap_table->numberOfEncodingTables);
  1256.     BYTE           *ptr;
  1257.     int             i, format, offset, seg_c2, found;
  1258.     int             platform, encoding_id;
  1259.     TTF_CMAP_ENTRY *table_entry;
  1260.     TTF_CMAP_FMT4  *encoding4;
  1261.  
  1262.     if(enc_found_ms) {
  1263.         handle_ms_encoding(glyph_list, encoding, unimap);
  1264.         return enc_type;
  1265.     } else if(enc_found_mac) {
  1266.         handle_mac_encoding(glyph_list, encoding, unimap);
  1267.         return 0;
  1268.     }
  1269.  
  1270.     if(force_pid != -1 && force_pid != 3) {
  1271.         fputs("*** Only platform ID == 3 is supported\n", stderr);
  1272.         exit(1);
  1273.     }
  1274.  
  1275.     enc_type = 0;
  1276.     found = 0;
  1277.  
  1278.     for (i = 0; i < num_tables && !found; i++) {
  1279.         table_entry = &(cmap_table->encodingTable[i]);
  1280.         offset = ntohl(table_entry->offset);
  1281.         encoding4 = (TTF_CMAP_FMT4 *) ((BYTE *) cmap_table + offset);
  1282.         format = ntohs(encoding4->format);
  1283.         platform = ntohs(table_entry->platformID);
  1284.         encoding_id = ntohs(table_entry->encodingID);
  1285.  
  1286.         if (platform == 3 && format == 4) {
  1287.             if(force_pid == 3) {
  1288.                 if(encoding_id != force_eid)
  1289.                     continue;
  1290.                 WARNING_1 fprintf(stderr, "Found Encoding PID=%d/EID=%d\n", 
  1291.                     force_pid, force_eid);
  1292.                 enc_type = 1;
  1293.             } else {
  1294.                 switch (encoding_id) {
  1295.                 case 0:
  1296.                     WARNING_1 fputs("Found Symbol Encoding\n", stderr);
  1297.                     break;
  1298.                 case 1:
  1299.                     WARNING_1 fputs("Found Unicode Encoding\n", stderr);
  1300.                     enc_type = 1;
  1301.                     break;
  1302.                 default:
  1303.                     WARNING_1 {
  1304.                         fprintf(stderr,
  1305.                         "****MS Encoding ID %d not supported****\n",
  1306.                             encoding_id);
  1307.                         fputs("Treating it like Symbol encoding\n", stderr);
  1308.                     }
  1309.                     break;
  1310.                 }
  1311.             }
  1312.  
  1313.             found = 1;
  1314.             seg_c2 = ntohs(encoding4->segCountX2);
  1315.             cmap_n_segs = seg_c2 >> 1;
  1316.             ptr = (BYTE *) encoding4 + 14;
  1317.             cmap_seg_end = (USHORT *) ptr;
  1318.             cmap_seg_start = (USHORT *) (ptr + seg_c2 + 2);
  1319.             cmap_idDelta = (short *) (ptr + (seg_c2 * 2) + 2);
  1320.             cmap_idRangeOffset = (short *) (ptr + (seg_c2 * 3) + 2);
  1321.             enc_found_ms = 1;
  1322.  
  1323.             handle_ms_encoding(glyph_list, encoding, unimap);
  1324.         }
  1325.     }
  1326.  
  1327.     if (!found) {
  1328.         if(force_pid != -1) {
  1329.             fprintf(stderr, "*** TTF encoding table PID=%d/EID=%d not found\n", 
  1330.                 force_pid, force_eid);
  1331.             exit(1);
  1332.         }
  1333.  
  1334.         WARNING_1 fputs("No Microsoft encoding, looking for MAC encoding\n", stderr);
  1335.         for (i = 0; i < num_tables && !found; i++) {
  1336.             table_entry = &(cmap_table->encodingTable[i]);
  1337.             offset = ntohl(table_entry->offset);
  1338.             encoding0 = (TTF_CMAP_FMT0 *) ((BYTE *) cmap_table + offset);
  1339.             format = ntohs(encoding0->format);
  1340.             platform = ntohs(table_entry->platformID);
  1341.             encoding_id = ntohs(table_entry->encodingID);
  1342.  
  1343.             if (format == 0) {
  1344.                 found = 1;
  1345.                 enc_found_mac = 1;
  1346.  
  1347.                 handle_mac_encoding(glyph_list, encoding, unimap);
  1348.             }
  1349.         }
  1350.     }
  1351.     if (!found) {
  1352.         fprintf(stderr, "**** No Recognised Encoding Table ****\n");
  1353.         exit(1);
  1354.     }
  1355.  
  1356.     return enc_type;
  1357. }
  1358.  
  1359. /*
  1360.  * Get the font metrics
  1361.  */
  1362. static void 
  1363. fnmetrics(
  1364.     struct font_metrics *fm
  1365. )
  1366. {
  1367.     char *str;
  1368.     static int fieldstocheck[]= {2,4,6};
  1369.     int i;
  1370.  
  1371.     fm->italic_angle = (short) (ntohs(post_table->italicAngle.upper)) +
  1372.         ((short) ntohs(post_table->italicAngle.lower) / 65536.0);
  1373.     fm->underline_position = (short) ntohs(post_table->underlinePosition);
  1374.     fm->underline_thickness = (short) ntohs(post_table->underlineThickness);
  1375.     fm->is_fixed_pitch = ntohl(post_table->isFixedPitch);
  1376.  
  1377.     fm->ascender = (short)ntohs(hhea_table->ascender);
  1378.     fm->descender = (short)ntohs(hhea_table->descender);
  1379.  
  1380.     fm->units_per_em =  ntohs(head_table->unitsPerEm);
  1381.  
  1382.     fm->bbox[0] = (short) ntohs(head_table->xMin);
  1383.     fm->bbox[1] = (short) ntohs(head_table->yMin);
  1384.     fm->bbox[2] = (short) ntohs(head_table->xMax);
  1385.     fm->bbox[3] = (short) ntohs(head_table->yMax);
  1386.  
  1387.     fm->name_copyright = name_fields[0];
  1388.     fm->name_family = name_fields[1];
  1389.     fm->name_style = name_fields[2];
  1390.     fm->name_full = name_fields[4];
  1391.     fm->name_version = name_fields[5];
  1392.     fm->name_ps = name_fields[6];
  1393.  
  1394.     /* guess the boldness from the font names */
  1395.     fm->force_bold=0;
  1396.  
  1397.     for(i=0; !fm->force_bold && i<sizeof fieldstocheck /sizeof(int); i++) {
  1398.         str=name_fields[fieldstocheck[i]];
  1399.         for(i=0; str[i]!=0; i++) {
  1400.             if( (str[i]=='B'
  1401.                 || str[i]=='b' 
  1402.                     && ( i==0 || !isalpha(str[i-1]) )
  1403.                 )
  1404.             && !strncmp("old",&str[i+1],3)
  1405.             && !islower(str[i+4])
  1406.             ) {
  1407.                 fm->force_bold=1;
  1408.                 break;
  1409.             }
  1410.         }
  1411.     }
  1412. }
  1413.  
  1414. /*
  1415.  * Get the path of contrours for a glyph.
  1416.  */
  1417.  
  1418. static void
  1419. glpath(
  1420.     int glyphno,
  1421.     GLYPH *glyf_list
  1422. )
  1423. {
  1424.     double          matrix[6];
  1425.     GLYPH          *g;
  1426.  
  1427.     g = &glyph_list[glyphno];
  1428.  
  1429.     matrix[0] = matrix[3] = 1.0;
  1430.     matrix[1] = matrix[2] = matrix[4] = matrix[5] = 0.0;
  1431.     draw_composite_glyf(g, glyf_list, glyphno, matrix, 0 /*level*/);
  1432. }
  1433.  
  1434. /*
  1435.  * Get the kerning data.
  1436.  */
  1437.  
  1438. static void
  1439. kerning(
  1440.     GLYPH *glyph_list
  1441. )
  1442. {
  1443.     TTF_KERN_SUB   *subtable;
  1444.     TTF_KERN_ENTRY *kern_entry;
  1445.     int             i, j;
  1446.     int             ntables;
  1447.     int             npairs;
  1448.     char           *ptr;
  1449.  
  1450.     if(kern_table == NULL) {
  1451.         WARNING_1 fputs("No Kerning data\n", stderr);
  1452.         return;
  1453.     }
  1454.     if(badpointer(kern_table)) {
  1455.         fputs("**** Defective Kerning table, ignored\n", stderr);
  1456.         return;
  1457.     }
  1458.  
  1459.     ntables = ntohs(kern_table->nTables);
  1460.     ptr = (char *) kern_table + 4;
  1461.  
  1462.     for (i = 0; i < ntables; i++) {
  1463.         subtable = (TTF_KERN_SUB *) ptr;
  1464.         if ((ntohs(subtable->coverage) & 0xff00) == 0) {
  1465.             npairs = (short) ntohs(subtable->nPairs);
  1466.             kern_entry = (TTF_KERN_ENTRY *) (ptr + sizeof(TTF_KERN_SUB));
  1467.  
  1468.             kern_entry = (TTF_KERN_ENTRY *) (ptr + sizeof(TTF_KERN_SUB));
  1469.             for (j = 0; j < npairs; j++) {
  1470.                 if( kern_entry->value != 0)
  1471.                     addkernpair(ntohs(kern_entry->left), 
  1472.                         ntohs(kern_entry->right), (short)ntohs(kern_entry->value));
  1473.                 kern_entry++;
  1474.             }
  1475.         }
  1476.         ptr += subtable->length;
  1477.     }
  1478. }
  1479.  
  1480.